package com.synergy.stockflow.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.synergy.stockflow.annotation.Log;
import com.synergy.stockflow.annotation.LogModule;
import com.synergy.stockflow.entity.SysRole;
import com.synergy.stockflow.entity.SysRolePerm;
import com.synergy.stockflow.entity.SysUser;
import com.synergy.stockflow.entity.SysUserRole;
import com.synergy.stockflow.entity.dto.RoleSaveDTO;
import com.synergy.stockflow.entity.vo.QuerySysRoleVO;
import com.synergy.stockflow.entity.vo.RolePermsVO;
import com.synergy.stockflow.entity.vo.SysRoleVO;
import com.synergy.stockflow.entity.vo.SysUserVO;
import com.synergy.stockflow.model.Result;
import com.synergy.stockflow.service.SysRolePermService;
import com.synergy.stockflow.service.SysRoleService;
import com.synergy.stockflow.service.SysUserRoleService;
import com.synergy.stockflow.service.SysUserService;
import com.synergy.stockflow.utils.ConvertUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/role")
@LogModule(name = "角色管理")
public class SysRoleController {
    private static final String PARAM_ROLE_ID = "roleCode";
    private final SysRoleService sysRoleService;

    private final SysRolePermService sysRolePermService;

    private final SysUserRoleService sysUserRoleService;

    private final SysUserService sysUserService;

    final
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    public SysRoleController(SysRoleService sysRoleService, SysRolePermService sysRolePermService, SysUserRoleService sysUserRoleService, SysUserService sysUserService, StringRedisTemplate stringRedisTemplate) {
        this.sysRoleService = sysRoleService;
        this.sysRolePermService = sysRolePermService;
        this.sysUserRoleService = sysUserRoleService;
        this.sysUserService = sysUserService;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @PostMapping("/list")
    @Log(title = "条件查询角色")
    public Result<List<SysRoleVO>> list(@RequestBody QuerySysRoleVO vo) {
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
        if (vo.getStatus() != null) {
            queryWrapper.eq(SysRole::getStatus, vo.getStatus());
        }
        queryWrapper.and(qw -> qw.like(SysRole::getRoleCode, vo.getDescription())
                .or().like(SysRole::getRoleName, vo.getDescription())
                .or().like(SysRole::getRemark, vo.getDescription()));

        List<SysRoleVO> list = ConvertUtils.toList(sysRoleService.list(queryWrapper), po -> ConvertUtils.copy(po, SysRoleVO.class));
        return Result.success(list);
    }

    @PostMapping("/page")
    @Log(title = "条件分页查询角色")
    public Result<Page<SysRoleVO>> page(@RequestBody QuerySysRoleVO vo) {
        Page<SysRole> page = new Page<>(vo.getCurrent(), vo.getSize());
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
        if (vo.getStatus() != null) {
            queryWrapper.eq(SysRole::getStatus, vo.getStatus());
        }
        queryWrapper.and(qw -> qw.like(SysRole::getRoleCode, vo.getDescription())
                .or().like(SysRole::getRoleName, vo.getDescription())
                .or().like(SysRole::getRemark, vo.getDescription()));

        Page<SysRoleVO> list = ConvertUtils.toPage(sysRoleService.page(page, queryWrapper), po -> ConvertUtils.copy(po, SysRoleVO.class));
        return Result.success(list);
    }

    @PostMapping("/save")
    @Log(title = "添加角色", description = "携带角色分配的权限添加角色")
    @CacheEvict(cacheNames = {"auth", "permission"}, allEntries = true)
    public Result<String> save(
            @RequestBody @Validated RoleSaveDTO dto
    ) {
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(dto, sysRole);

        boolean saved = sysRoleService.addRole(sysRole, dto.getPerms());
        return Result.success(saved ? "操作成功" : "操作失败");
    }

    @PostMapping("/edit")
    @Log(title = "设置角色", description = "携带角色分配的权限设置角色")
    @CacheEvict(cacheNames = {"auth", "permission"}, allEntries = true)
    public Result<String> edit(
            @RequestBody @Validated RoleSaveDTO dto
    ) {
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(dto, sysRole);

        boolean saved = sysRoleService.updateRole(sysRole, dto.getPerms());
        return Result.success(saved ? "操作成功" : "操作失败");
    }

    // 接口 /role/perms
    @GetMapping("/perms")
    @Log(title = "查询角色下的权限编号", description = "根据角色编码查询权限编号集合")
    public Result<List<Long>> getPerms(String roleCode) {
        SysRole sysRole = sysRoleService.getByRoleCode(roleCode);
        LambdaQueryWrapper<SysRolePerm> eq = new LambdaQueryWrapper<>();
        eq.eq(SysRolePerm::getSysRoleId, sysRole.getRoleId());
        List<SysRolePerm> list = sysRolePermService.list(eq);
        return Result.success(list.stream().map(SysRolePerm::getSysPermissionId).collect(Collectors.toList()));
    }


    @PostMapping("/detail")
    @Log(title = "根据角色编码查看详情")
    public Result<SysRole> detail(@RequestBody Map<String, Integer> param) {
        Integer roleId = param.get(PARAM_ROLE_ID);
        return Result.success(sysRoleService.getById(roleId));
    }

    @PostMapping("/update")
    @CacheEvict(cacheNames = {"auth", "permission"}, allEntries = true)
    public Result<Boolean> update(@RequestBody SysRole sysRole) {
        return Result.success(sysRoleService.updateById(sysRole));
    }

    @PostMapping("/update_perms")
    @CacheEvict(cacheNames = {"auth", "permission"}, allEntries = true)
    public Result<Boolean> updatePerms(@RequestBody RolePermsVO rolePermsVO) {
        List<Long> idList = rolePermsVO.getIdList();
        Integer roleId = rolePermsVO.getRoleId();
        if (idList == null || idList.isEmpty()) {
            LambdaQueryWrapper<SysRolePerm> queryWrapper = new LambdaQueryWrapper<>();
            return Result.success(sysRolePermService.remove(queryWrapper.eq(SysRolePerm::getSysRoleId, roleId)));
        }
        Date date = new Date();
        List<SysRolePerm> list = ConvertUtils.toList(idList, id -> {
            SysRolePerm sysRolePerm = new SysRolePerm();
            sysRolePerm.setSysRoleId(roleId);
            sysRolePerm.setSysPermissionId(id);
            sysRolePerm.setCreateTime(date);
            return sysRolePerm;
        });
        return Result.success(sysRolePermService.saveBatch(list, 1000));
    }

    @PostMapping("/list_bound_users")
    public Result<List<SysUserVO>> listBoundUsers(@RequestBody Map<String, String> param) {
        String roleCode = param.get(PARAM_ROLE_ID);
        SysRole sysRole = sysRoleService.getByRoleCode(roleCode);
        LambdaQueryWrapper<SysUserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUserRole::getSysRoleId, sysRole.getRoleId());
        List<SysUserRole> list = sysUserRoleService.list(queryWrapper);
        List<Long> userIds = list.stream().map(SysUserRole::getSysUserId).collect(Collectors.toList());
        List<SysUser> sysUsers = sysUserService.listByIds(userIds);
        List<SysUserVO> vos = ConvertUtils.toList(sysUsers, SysUserVO::fromEntity);
        return Result.success(vos);
    }


    @PostMapping("/remove")
    @Log(title = "删除角色")
    @CacheEvict(cacheNames = {"auth", "permission"}, allEntries = true)
    public Result<Boolean> remove(@RequestBody Map<String, String> param) {
        String roleCode = param.get(PARAM_ROLE_ID);
        SysRole sysRole = sysRoleService.getByRoleCode(roleCode);
        return Result.success(sysRoleService.removeById(sysRole.getRoleId()));
    }

    @PostMapping("/remove_batch")
    @Log(title = "批量删除角色")
    @CacheEvict(cacheNames = {"auth", "permission"}, allEntries = true)
    public Result<Integer> batchRemove(@RequestBody List<String> codes) {
        return Result.success(sysRoleService.removeBatchByCodes(codes));
    }
}
